package dom;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class Test_Xpath {

    public static void main(String[] args) {
        Test_Xpath.testNo_Namespace();
//        Test_Xpath.test_Namespace();
        
    }

    
    /**
     * 搜索有命名空间的xml文件
     */
    private static void test_Namespace() {
        
        File xmlFile=new File("./src/student.xml");
        SAXReader saxReader=new SAXReader();
        Map<String,String> namespaceURIs=new HashMap<String, String>();
        
        /**
         * 设置命名空间，注意在xml文件中命名空间的前缀可以为空（xmlns="http://www.example.org/student"）
         * 但是在这里不能为空，必须有前缀
         */
        namespaceURIs.put("stu", "http://www.example.org/student");
        namespaceURIs.put("jdbc","http://www.example.org/jdbc");
        saxReader.getDocumentFactory().setXPathNamespaceURIs(namespaceURIs);
        try {
            Document document=saxReader.read(xmlFile);
            
            Element rootElment=document.getRootElement();
            Element parentElement=rootElment.element("root");
            
            /**
             * 从document节点开始搜索——绝对路径 "/other/root/student"
             * 中以/打头表示以绝对路径方法，而这个xml文件里的根节点为other，
             * 这里的other、root、student节点都是stu命名空间的xml文件里的，所以要加stu前缀
             */
            List<Element> list = document.selectNodes("/stu:other/stu:root/stu:student");
//             System.out.println(list.size());

            /**
             * 从other路径搜索——相对路径
             */
            list = rootElment.selectNodes("stu:root/stu:student");
//             System.out.println(list.size());

            /**
             * 从root目录(parentElement节点)搜索起_全文路径，
             * 这里的parentElemen换成其他节点比如document或者rootElement也是可以的,
             * 只要这个节点是被搜索节点的父节点即可
             */
            list = parentElement.selectNodes("//stu:student");
//             System.out.println(list.size());

            /**
             * 找到属性id=03的节点
             */
            list = parentElement.selectNodes("/stu:other/stu:root/stu:student[@id=03]");
            Element element_id03 = list.get(0);
//             System.out.println(element_id03.element("name").getText());

            /**
             * 查找性别为男的节点,没有加@的就是指元素节点的值，加了@是指节点的属性的值
             * 属性不用加前缀外，元素节点必须加前缀
             */
            list = parentElement.selectNodes("stu:student[stu:sex='男']");
//             System.out.println(list.size());

            /**
             * 查找年龄在某一范围的节点
             */
            list = parentElement.selectNodes("stu:student[stu:age>=15 and stu:age<50]");
//             System.out.println(list.size());

            /**
             * 查找名称中有a字符的节点，相当于sql中的模糊查询(like),
             * xpath中也有函数，这里的contains(name,'张三') 就是一个函数，
             * student[contains(name,'张三')] ：
             * 表示查找子节点为name且name的值含有‘张三’的student节点
             */
            list = parentElement.selectNodes("stu:student[contains(stu:name,'张三')]");
//             System.out.println(list.size());

            /**
             * 查找名称为包含a的字符,并且性别为男的，并且年龄在一个范围内
             */
            list = parentElement.selectNodes("stu:student[contains(stu:name,'张三') and stu:sex='男' and stu:age>=10 ]");
//            System.out.println(list.size());
   
            Element jdbcElement=(Element)document.selectSingleNode("/stu:other/jdbc:jdbcInfo");
            
            System.out.println(jdbcElement.elementText("jdbcDriver"));
            System.out.println(jdbcElement.elementText("url"));
            System.out.println(jdbcElement.elementText("password"));
            System.out.println(jdbcElement.elementText("user"));
 
        } catch (DocumentException e) {
            e.printStackTrace();
        }

    }

    /**
     * 搜索没有命名空间的xml文件
     */
    private static void testNo_Namespace() {
        File xmlFile = new File("./src/no_namespace.xml");

        SAXReader saxReader = new SAXReader();

        try {
            Document document = saxReader.read(xmlFile);

            Element rootElment = document.getRootElement();

            Element parentElement = (Element) rootElment.elements("root").get(0);

            /**
             * 从document节点开始搜索——绝对路径 "/other/root/student"
             * 中以/打头表示以绝对路径方法，而这个xml文件里的根节点为other
             */
            List<Element> list = document.selectNodes("/other/root/student");
            // System.out.println(list.size());

            /**
             * 从other路径搜索——相对路径
             */
            list = rootElment.selectNodes("root/student");
            // System.out.println(list.size());

            /**
             * 从root目录(parentElement节点)搜索起_全文路径，
             * 这里的parentElemen换成其他节点比如document或者rootElement也是可以的,
             * 只要这个节点是被搜索节点的父节点即可
             */
            list = parentElement.selectNodes("//student");
            // System.out.println(list.size());

            /**
             * 找到属性id=03的节点
             */
            list = parentElement.selectNodes("/other/root/student[@id=03]");
            Element element_id03 = list.get(0);
            // System.out.println(element_id03.element("name").getText());

            /**
             * 查找性别为男的节点,没有加@的就是指元素节点的值，加了@是指节点的属性的值
             */
            list = parentElement.selectNodes("student[sex='男']");
            // System.out.println(list.size());

            /**
             * 查找年龄在某一范围的节点
             */
            list = parentElement.selectNodes("student[age>=15 and age<50]");
            // System.out.println(list.size());

            /**
             * 查找名称中有a字符的节点，相当于sql中的模糊查询(like),
             * xpath中也有函数，这里的contains(name,'张三') 就是一个函数，
             * student[contains(name,'张三')] ：
             * 表示查找子节点为name且name的值含有‘张三’的student节点
             */
            list = parentElement.selectNodes("student[contains(name,'张三')]");
            // System.out.println(list.size());

            /**
             * 查找名称为包含a的字符,并且性别为男的，并且年龄在一个范围内
             */
            list = parentElement.selectNodes("student[contains(name,'张三') and sex='男' and age>=10 ]");
            System.out.println(list.size());

        } catch (DocumentException e) {
            e.printStackTrace();
        }

    }
}